// 07-图5 Saving James Bond - Hard Version
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

/* Array.c =================================*/
int **init2D(int n) {
    int** a = (int**) calloc(sizeof(int*), n);
    for (int i=0; i<n; i++) {
        a[i] = (int*) calloc(sizeof(int), n);
    }
    return a;
}

void free2D(int **a, int n) {
    for (int i=0; i<n; i++) {
        free(a[i]);
    }
    free(a);
}

void print1D(char* name, int array[], int n) {
    printf("%s: ", name);
    for (int i=0; i < n; i++) {
        printf("%d ", array[i]);
    }
    printf("\n");
}

void print2D(int **m, int n, int defaultWeight) {
    for (int i=-1; i<n; i++) {
        printf("[%3d]", i);
    }
    printf("\n");
    for (int i=0; i<n; i++) {
        printf("[%3d]", i);
        for (int j=0; j<n; j++) {
            if (m[i][j] == defaultWeight) {
                printf("    -");
            } else {
                printf("%5d", m[i][j]);
            }
        }
        printf("\n");
    }
}

/* MGraph ====================================*/
// 定义权重的最大值
#define MaxWeight 0x7FFF
// 无路径
#define Connectionless -1
// 有向图, 无向图
#define DirectedGraph 1
#define UndirectedGraph 0

// 权重类型
typedef int WeightType;
typedef struct Edge Edge;
struct Edge {
    int v, w;
    WeightType weight;
};

typedef struct MGraph MGraph;
struct MGraph {
    int directed; // 1-有向图，0-无向图
    int defaultWeight; // 默认的无连接的权重
    int vertexNum; // 顶点数
    int edgeNum;   // 边数
    WeightType **g; // 邻接矩阵
};

Edge createEdge(int v, int w, int weight) {
    Edge e;
    e.v = v;
    e.w = w;
    e.weight = weight;
    return e;
}

MGraph *createGraph(int directed, int defaultWeight, int vertexNum) {
    MGraph* g = (MGraph*)calloc(sizeof(MGraph), 1);
    g->directed = directed;
    g->defaultWeight = defaultWeight;
    g->vertexNum = vertexNum;
    // 初始化邻接矩阵
    g->g = (WeightType**) malloc(sizeof(WeightType*) * vertexNum);
    for (int v=0; v < g->vertexNum; v++) {
        g->g[v] = (WeightType*) malloc(sizeof(WeightType) * vertexNum);
        for (int w=0; w < g->vertexNum; w++) {
            g->g[v][w] = defaultWeight;
        }
    }
    return g;
}

void freeGraph(MGraph* g) {
    free2D(g->g, g->vertexNum);
    free(g);
}

// 判断图的两个顶点 v1, v2 之间是否有直接连接
int isConnection(MGraph* g, int v1, int v2) {
    return g->g[v1][v2] != g->defaultWeight;
}

void insertEdge(MGraph* g, int v1, int v2, WeightType weight) {
    g->g[v1][v2] = weight;
    if (g->directed == UndirectedGraph) {
        g->g[v2][v1] = weight;
    }
}

// 从标准输入读取边信息，顶点下标从0开始
void readEdgeV0(MGraph* g, int edgeNum) {
    g->edgeNum = edgeNum;
    for (int i=0; i<edgeNum; i++) {
        int v1, v2;
        scanf("%d %d", &v1, &v2);
        insertEdge(g, v1, v2, 1);
    }
}

void readEdgeV0WithWeight(MGraph* g, int edgeNum) {
    g->edgeNum = edgeNum;
    for (int i=0; i<edgeNum; i++) {
        int v1, v2;
        WeightType dist;
        scanf("%d %d %d", &v1, &v2, &dist);
        insertEdge(g, v1, v2, dist);
    }
}

// 从标准输入读取边信息，顶点下标从1开始编号
void readEdgeV1(MGraph* g, int edgeNum) {
    g->edgeNum = edgeNum;
    for (int i=0; i<edgeNum; i++) {
        int v1, v2;
        scanf("%d %d", &v1, &v2);
        insertEdge(g, --v1, --v2, 1);
    }
}

void readEdgeV1WithWeight(MGraph* g, int edgeNum) {
    g->edgeNum = edgeNum;
    for (int i=0; i<edgeNum; i++) {
        int v1, v2;
        WeightType dist;
        scanf("%d %d %d", &v1, &v2, &dist);
        insertEdge(g, --v1, --v2, dist);
    }
}

void printGraph(MGraph* g) {
    printf("Graph n=%d, e=%d\n", g->vertexNum, g->edgeNum);
    print2D(g->g, g->vertexNum, g->defaultWeight);
}

/* Floyed =====================================*/
int floyed(MGraph* g, WeightType **d, int **path) {
    // 初始化
    for (int i=0; i<g->vertexNum; i++) {
        for (int j=0; j<g->vertexNum; j++) {
            d[i][j] = g->g[i][j];
            path[i][j] = Connectionless;
        }
    }
    for (int k=0; k<g->vertexNum; k++) {
        for (int i=0; i<g->vertexNum; i++) {
            for (int j=0; j<g->vertexNum; j++) {
                if (d[i][k] + d[k][j] < d[i][j]) {
                    d[i][j] = d[i][k] + d[k][j];
                    if (i==j && d[i][j]<0) {
                        // 发现负值圈
                        return 0;
                    }
                    path[i][j] = k;
                }
            }
        }
    }
    return 1;
}

/* current ================================*/
// #define MaxVertexNum 101

typedef struct Point Point;
struct Point {
    int x, y;
};

// 使用全局变量
// 鳄鱼坐标点
Point* points;
// 岛半径
double islandRadius = 15.0/2;
// 顶点数（鳄鱼数+1），跳跃距离
int vertexNum, jumpDistance;

// 是否可以从v跳到w
int jump(Point* v, Point* w) {
    double d = sqrt((v->x - w->x)*(v->x - w->x) + (v->y - w->y)*(v->y - w->y));
    return jumpDistance >= d;
}

// 第一跳是否可以跳到目标点v
int firstJump(Point* v, double *d) {
    *d = sqrt(v->x*v->x + v->y*v->y);
    return (islandRadius + jumpDistance) >= *d;
}

// 是否可以跳到岸边
int isSafe(Point* v) {
    return (50 - abs(v->x)) <= jumpDistance || (50 - abs(v->y)) <= jumpDistance;
}

MGraph* buildGraph() {
    int n;
    scanf("%d %d", &n, &jumpDistance);

    vertexNum = n + 1;
    points = (Point*)calloc(sizeof(Point), vertexNum);
    MGraph* g = createGraph(UndirectedGraph, MaxWeight, vertexNum);

    // 读入顶点，从1开始存储，0是小岛
    for (int i=1; i<=n; i++) {
        scanf("%d %d", &points[i].x, &points[i].y);
        // 如果可以从小岛跳到输入的鳄鱼，在图中建立边
        double fd;
        if (firstJump(&points[i], &fd)) {
            insertEdge(g, 0, i, (int)(fd-islandRadius));
        }
    }
    // 建立其他可以跳的鳄鱼之间的边
    for (int i=1; i<=n; i++) {
        for (int j=i+1; j<=n; j++) {
            if (jump(&points[i], &points[j])) {
                insertEdge(g, i, j, jumpDistance);
            }
        }
    }
    return g;
}

void printPath(int** path, int s, int e) {
    int k = path[s][e];
    if (k == Connectionless) {
        return;
    }
    printPath(path, s, k);
    printf("%d %d\n", points[k].x, points[k].y);
    printPath(path, k, e);
}

void findPath(MGraph* g) {
    // 使用floyed算法，求各点之间的距离
    WeightType** d = init2D(g->vertexNum);
    int** path = init2D(g->vertexNum);
    if (!floyed(g, d, path)) {
        free2D(d, g->vertexNum);
        free2D(path, g->vertexNum);
        return;
    }
    // printf("d:\n");
    // printD2(d, g->vertexNum);
    // printf("path:\n");
    // printD2(path, g->vertexNum);

    WeightType minDist = MaxWeight;
    int crocody = -1;
    for (int i=1; i<g->vertexNum; i++) {
        if (isSafe(&points[i]) && minDist > d[0][i]) {
            minDist = d[0][i];
            crocody = i;
        }
    }
    // 没有找到逃跑的路径
    if (crocody == -1) {
        free2D(d, g->vertexNum);
        free2D(path, g->vertexNum);
        printf("0\n");
        return;
    }
    // 计算跳数，因第一跳的距离是鳄鱼与小岛之间的真实距离，通过余数判断是否需要+1
    // 最后一次跳到岸，+1
    printf("%d\n", minDist/jumpDistance + (minDist%jumpDistance>0 ? 1:0) + 1);
    // printf("crocody = %d\n", crocody);
    printPath(path, 0, crocody);
    printf("%d %d\n", points[crocody].x, points[crocody].y);
    free2D(d, g->vertexNum);
    free2D(path, g->vertexNum);
}

int main() {
    MGraph* g = buildGraph();
    // printGraph(g);
    // 判断是否可以一步跳到岸
    if (jumpDistance + islandRadius >= 50) {
        printf("1\n");
    } else {
        findPath(g);
    }
    freeGraph(g);
    free(points);
    return 0;
}
